use std::{collections::BTreeMap, sync::OnceLock};

use base_data::channel::{Channel, ChannelCallDirection, ChannelState};
use tokio::sync::mpsc;
use tools::{error::Error, global_defin::tokio_runtime::get_rt, ResultEx};
use tracing::{debug, error, info, span, trace, warn, Instrument, Level};

use crate::sip2::dialog::dialog::{dialog_id, Dialog};

use super::{
	dialog::{dialog_iden::DialogIdent, sipdata::SipData, DialogEvent, DialogMessage},
	transport::{TransportLayerPacket, TransportProtocol},
	SipMethod,
};

pub static DIALOG_DISTIBUTE: OnceLock<mpsc::Sender<DialogEvent>> = OnceLock::new();

///sip消息处理分发器启动.
///
/// 只是为了启动分发协程..对应的sip协议处理只启动一次此方法.
/// 返回向此发布者发送消息的发送者
pub(crate) fn start_distribute<F>(
	create_channel: &'static F,
	to_reg: mpsc::Sender<(SipData, TransportProtocol)>,
) -> mpsc::Sender<DialogEvent>
where
	F: Fn(Channel) + Send + Sync,
{
	let (sender, recv_command) = mpsc::channel(2048);
	DIALOG_DISTIBUTE.get_or_init(|| sender.clone());

	let span = span!(Level::ERROR, "");
	get_rt().spawn(distribute(recv_command, sender.clone(), to_reg, create_channel).instrument(span));

	sender
}

///sip消息处理分发器启动.
///
/// 接收双向的消息,并进行转发.
/// 因为收到的sip数据是底层字节.所以在这里调用转码方式转成sip数据包
/// 判断收到的sip是否是创建dialog..如果是的话生成协程等待处理.如inv..而regist做为一个独立的协程,处理所有登录者的相关处理.
/// 创建dialog时,同时调用相关方法创建一个业务逻辑层.并将此dialog和逻辑层两个协程使用消息对应起来.
/// 后续收到的sip消息直接发给对应的dialog协程,其余由dialog协程和业务协程自己处理
async fn distribute<F>(
	mut recv_transport: mpsc::Receiver<DialogEvent>,
	to_distribute: mpsc::Sender<DialogEvent>,
	to_reg: mpsc::Sender<(SipData, TransportProtocol)>,
	create_channel: &'static F,
) where
	F: Fn(Channel) + Send + Sync,
{
	info!("sip消息分发器启动");
	//用来保存对应于业务逻辑的通道.保存的状态为DialogId
	let mut dialogs = BTreeMap::<DialogIdent, mpsc::Sender<DialogMessage>>::new();

	loop {
		match recv_transport.recv().await {
			Some(DialogEvent::TransportLayerPacket(p)) => {
				trace!("收到待分发的数据:{:?}",p);
				let pro = p.protocol.clone();

				match handle_sip_packet(p, &to_distribute, &mut dialogs, &to_reg, create_channel) {
					Ok(_) => {}
					Err(Error::SipErrorRecover(buf)) => {
						trace!("返回一个数据:{:?}",buf);
						let _ = pro.send(buf);
					}
					Err(e) => {
						error!("处理sip数据包失败,e:{}", e);
					}
				}
			}
			Some(DialogEvent::NewDialog(dia, s)) => {
				//收到一个已经创建好的dialog..这里的操作一般表示是一个blag.不需要生成rtp.但需要注册,并接收消息
				dialogs.insert(dia.ident().clone(), s.clone());
				let dialog_ = dia.id;
				let span = span!(Level::ERROR, "", dialog_);
				//启动dialog处理
				get_rt().spawn(dia.start_run().instrument(span));
			}
			Some(DialogEvent::Close(id)) => {
				trace!("接收到dialog关闭事件,id:{id}");
				dialogs.retain(|k, _| k.id() != id);
			}

			None => {
				warn!("sip distribute()所有发送者都退出了.");
				info!("sip消息分发器退出");
				return;
			}
			Some(DialogEvent::ShowDialogs) => {
				info! {"dialog count:{}",dialogs.len()};
				for (k, d) in dialogs.iter() {
					info!("ident:{:?},dialog:{:?}", k, d);
				}
			}
		}
	}
}

///对从传输层收到的包进行处理.
///
/// 此方法仅处理收到的sip包...
#[inline]
fn handle_sip_packet<'a, F>(
	packet: TransportLayerPacket,
	to_distribute: &mpsc::Sender<DialogEvent>,
	dialogs: &mut BTreeMap<DialogIdent, mpsc::Sender<DialogMessage>>,
	to_reg: &mpsc::Sender<(SipData, TransportProtocol)>,
	create_channel: &F,
) -> ResultEx<()>
where
	F: Fn(Channel) + Send + Sync + 'static,
{
	let sip_data = SipData::decode_transport_layer_packet(packet.data);
	sip_data.verify()?;

	//在一个dialog中?直接发送消息处理
	if let Some(sender) = dialogs.get(&sip_data.call_id.bytes().into()) {
		sender.try_send(DialogMessage::SipData(sip_data))?;
		return Ok(());
	} else if sip_data.is_in_dialog() {
		trace!("收到一个没有找到的callid的包");
		return Err(Error::SipErrorRecover(sip_data.generate_call_not_exist()));
	}

	//这里是新创建事件...上面已经进行了返回
	//目前只处理呼入和注册两个需要调用方法进行创建一个处理者,其余向已经存在处理者发消息
	match sip_data.direction {
		super::SipDirection::Request(SipMethod::Invite) => {
			let ident = DialogIdent::new(dialog_id(), sip_data.call_id.bytes().clone());
			debug!("新创建一个sip的呼入.ident:{:?}", ident);

			let (dist_t_dialog, dist_r_dialog) = mpsc::channel(1024);
			let (s, r) = mpsc::channel(1024);
			let (s_d, r_d) = mpsc::channel(1024);
			
			let dialog = Dialog::from_sip(
				ident.id(),
				sip_data,
				packet.protocol,
				s,
				r_d,
				dist_r_dialog,
				to_distribute.clone(),
				dist_t_dialog.clone(),
			)?;

			let channel = Channel {
				id: ident.id(),
				state: ChannelState::Down,
				direction: ChannelCallDirection::InBound,
				caller_num: dialog.caller_num(),
				dest_num: dialog.dest_num(),
				to_switch: s_d,
				from_switch: r,
			};

			create_channel(channel);
			dialogs.insert(dialog.ident().clone(), dist_t_dialog.clone());

			let dialog_ = dialog.id;
			let span = span!(Level::ERROR, "", dialog_);
			//启动dialog处理
			get_rt().spawn(dialog.start_run().instrument(span));
		}
		//注册消息直接转给注册处理器
		super::SipDirection::Request(SipMethod::Register) => {
			let _ = to_reg.try_send((sip_data, packet.protocol));
		}

		super::SipDirection::Request(SipMethod::Subscribe)
		| super::SipDirection::Request(SipMethod::Notify)
		| super::SipDirection::Request(SipMethod::Publish)
		| super::SipDirection::Request(SipMethod::Options) => {
			// 这里直接向回发200ok,不再向下处理
			let buf = sip_data.generate_ok();
			packet.protocol.send(buf);
		}
		_ => {
			error!("distribute_sip,未实现的操作");
		}
	}

	Ok(())
}
